java 基础知识 动态代理 cglib代理
一、cglib代理介绍
cglib代理是实现动态代理的另一种方式,CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,CGLIB是一个好的选择
二、cglib的原理
- 动态生成目标类的代理类,重写代理类的所有非final修饰的方法,子类使用方法拦截的方式实现目标类的增强,所以cglib代理比jdk反射代理效率更高,并且能代理类,而jdk代理只能代理接口
- 底层使用asm字节码框架生成代理类,而不是使用反射生成类
- 缺点不能代理被final修饰的方法
三、cglib代理的实现
public static void main(String[] args) { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "resource"); Dog dog =new Dog(); Enhancer enhancer =new Enhancer(); //设置目前类 enhancer.setSuperclass(Dog.class); //设置拦截器 enhancer.setCallback(new MethodInterceptor() { public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("呵呵,我是增强"); return methodProxy.invokeSuper(o,objects); } }); Dog dogProxy = (Dog) enhancer.create(); dogProxy.run(); }
四、invokeSuper()方法
因为cglib代理是继承目标类,并且重写方法,所以这里调用invokesuper方法,调用父类的方法
五、cglib原理
上图可以看到cglib方式会在内存中生成,3个字节码文件.可以使用 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, “resource”);方法将字节码文件写到相关目录。
- 可以看到代理类实现了目标代理类
- 可以看到重写run方法,先回去回调方法,如果获取不到就加载回调方法,执行intercept 方法
- FastClass机制
FastClass提出了index下标的概念,通过index保存方法的引用信息,将反射调用转化为方法的直接调用,体现所谓的fast - 通过方法名计算hashcode值,通过hashcode找到方法对应的index
- 通过index 调用invoke方法,invoke方法通过index判断执行那个方法
总结
- 动态代理类通过实现invocationHandler接口
- 通过
Proxy.newProxyInstance(factory.getClass().getClassLoader(),person.getClass().getInterfaces(),this)方法
复制一份代理的类并且生成字节码文件到内存中,
生成的代理类 继承了Proxy类 并且实现了代理接口
调用生成的动态代理类中实现的方法,其中调用了其实现的方法,在方法中通过invocationHandler的invoke()方法
jdk动态代理的缺点 不能代理类,需要实现invocationHandler接口
jdk动态代理和cglib生成字节码的方式不通 - cglib动态代理 可以动态代理类
因为cglib动态生成的类是继承原类,所以可以动态代理到类 - jdk动态代理实现了自己的顶层接口继承了proxy类
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment